package com.yoyo.dao.base;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

public abstract class BaseDaoSupport<T> {
	
	@PersistenceContext 
	protected EntityManager em ;
	
	protected Class<T> entityClass = getEnityClass();

	@SuppressWarnings("unchecked")
	private Class<T> getEnityClass() {
		Type parentType = getClass().getGenericSuperclass();
		if(parentType instanceof ParameterizedType){
			ParameterizedType ptype = (ParameterizedType)parentType ;
			return (Class<T>)ptype.getActualTypeArguments()[0] ;
		}
		return null;
	}
	
	public void delete(Object entityid) {
		delete(new Object[]{entityid});		
	}

	public void delete(Object[] entityids) {
		for(Object id:entityids){
			em.remove(em.getReference(entityClass, id));
		}		
	}

	public void save(Object entity) {
		em.persist(entity);
	}

	public void update(Object entity) {
		em.merge(entity);
	}
	
	public T find(Object entityid) {
		return em.find(entityClass, entityid);
	}
	
	public List<T> findAll() {
		return findAll(null,null,null);
	}
	
	public List<T> findAll(String where,Object[] params) {
		return findAll(where,params,null);
	}
	
	@SuppressWarnings("unchecked")
	//@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
	public List<T> findAll(String where,Object[] params,LinkedHashMap<String,String> orderby) {
		String entityName = getEntityName(entityClass);
		Query query = em.createQuery("select o from "+entityName+" o "+(where==null?"":" where "+where)+buileOrderBy(orderby));
		setQureyParams(query,params);	
		List<T> list = query.getResultList();
		return list ;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findOrder(String order,int start,int max) {
		LinkedHashMap<String,String> orderby = new LinkedHashMap<String,String>();
		orderby.put("id", order);
		String entityName = getEntityName(entityClass);
		Query query = em.createQuery("select o from "+entityName+" o "+buileOrderBy(orderby));
		List<T> list ;
		if(max==0){
			list = query.getResultList();
		}else{ 
			list = query.setMaxResults(max).setFirstResult(start).getResultList();
		}
		return list ;
	}

	protected void setQureyParams(Query query,Object[] params){
		if(params!=null && params.length>0){
			for(int i=0;i<params.length;i++){
				query.setParameter(i+1, params[i]);
			}
		}
	}

	protected String buileOrderBy(LinkedHashMap<String,String> orderby){
		if(orderby==null || orderby.size()==0){
			return "" ;
		}else{
			StringBuffer sb = new StringBuffer();
			sb.append(" order by ");
			for(String key : orderby.keySet()){
				sb.append("o.").append(key).append(" ").append(orderby.get(key)).append(",");
			}
			sb.deleteCharAt(sb.length()-1);
			return sb.toString();
		}
	}
	
	protected String getEntityName(Class<T> entityClass){
		String entityName = entityClass.getSimpleName();
		Entity entity = entityClass.getAnnotation(Entity.class);
		if(entity!=null && !"".equals(entity.name())){
			entityName = entity.name() ;
		}
		return entityName ;
	}

}
